package com.xyy.saas.payment.adpater.fumin.util;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.xyy.saas.payment.adpater.fumin.config.EncryptorsClassEnum;
import com.xyy.saas.payment.adpater.fumin.encrypt.AESUtils;
import com.xyy.saas.payment.adpater.fumin.encrypt.Encryptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

/**
 * 验签解密获取加解密bean等
 *
 * @author yuancheng@belink.com
 * @date 2018/12/4
 */
public class VerifyAndDecryptUtil {

    private static final Logger logger = LoggerFactory.getLogger(VerifyAndDecryptUtil.class);

    private static Map<String, Encryptor> encryptorMap = new HashMap<>();

    /**
     * 从本地缓存中获取加解密的bean
     *
     * @param type 加解密类型
     */
    public static Encryptor getEncryptor(String type) throws Exception {
        String typeUpperCase = type.toUpperCase(Locale.getDefault());
        Encryptor encryptor = encryptorMap.get(typeUpperCase);
        if (null == encryptor) {
            Class<? extends Encryptor> clazz = EncryptorsClassEnum.valueOf(typeUpperCase).getClazz();
            encryptor = clazz.newInstance();
            encryptorMap.put(type, encryptor);
        }
        return encryptor;
    }

    /**
     * 对响应结果进行签名验证
     * @param encryptedResult 加密签名后的数据
     * @param publicKey 平台公钥
     * @return 根据响应结果解析的json对象
     */
    public static JSONObject verifySignature(String encryptedResult, String publicKey) throws Exception {
        Map<String, Object> map = JSONObject.parseObject(
                encryptedResult, new TypeReference<TreeMap<String, Object>>() {});
        Object obj = map.remove("signData");
        JSONObject json = new JSONObject(map);
        Encryptor encryptor = VerifyAndDecryptUtil.getEncryptor(json.getString("signType"));

        boolean bl = encryptor.verifySignature(json.toJSONString(), obj.toString(), publicKey);
        if (!bl) {
            logger.error("The result signature verify failed, encryptedResult is : {} ", encryptedResult);
            throw new IllegalArgumentException("Verify signature failed.");
        }
        return json;
    }

    public static void main(String[] args) throws Exception {
        System.out.println(decryptResult(JSONObject.parseObject("{\"data\":\"pli/YGgxgtkKHN3DzucrwMtEmZEJwn5ibVR9sc/zFXFg7W5n5Y2fIB6B2N7Gk1tU0XnR7XdnsNgqqWgbF4AkzLY/ke8JQa7zkeznVuoL4UuIm991JBOq1cH7XG1umMhaveW0BKsaV4qaGUTU0UFp5d/D+EI0s9U1JksFfDHXEX1GMzuHk7KydQJuP+0PSImE4Ly77zuphLoDviYF06k0KBC9KWc4i0k9FLPB1NAkf7/16kA4TXOTvAgEC6gvUcgRwdAQYVg/klaWd11nEfBSNv4iTqa9xibW4xLiZJ18woqrCIrOTaaXWhr5dXndzkJ0drpEJOxVFY2FfWBlECIg13B7JKyQBzFxKa/uWf7Dm3U7l8oAHbO+imRdGCo9Q58/MDKzSAHQ9i2C3AEJyTniiNFOnZGjTJ4QBXyUV92MWsKEt4TPBlm8Bu6RJD5FX2S9w0pBBb97O9po5FvaTGqxZH81uHapghxcCvhq3TrZI+s+KP58eW3P3KfMQAZpi8VIVvMnJz9aQ9sPAjoHmF+ivIMJM+XwFuBhNANwLshVTAoAM6CL/vDp8oM5gYVj0pzw\",\"encryptType\":\"RSA\",\"randomKeyEncrypt\":\"QKjrrRNbBVS/Crkh4ZVoe0BtgO1y4P4recZx/58hKJoKb9yjMPskafSXmtmWnDl3tHY7sm5px2VkkYVPjhpdUtcGeopKlsw3bv232PQ7Lr340dWuwXrM/bYZdfyAJsZcpEnqtrVTYzzlz+n5wJ8Xow/2LuSBkajvFapFhpmjN3+Wf1tkvCHJJ8epI8kdRSwLduyI+hNN8t6K3r7HeGoesN40LyaytBs6pOVDQZ3EtgtHGC9tlnymTXRXOCULxD2i8VlS1zX4PtzAAmKOCHiTEIjye/sSeW9yhRii6XEqFCg1fDXLvkqZHT0iTFEHymA4BpaLGteznzpOevhzEuMfsQ==\",\"signData\":\"SioidPi+VQxFH67X3Ufdb3yYW1xOYdafFA/9NMbh8ykQklak+f7BJjV4iw8UzVQLBFgYIQMIo7t6JUn8GvjS4Bv0q5UMY/incOeGsYysEPUPrSyics1WhMhZz+yIXkLYYKdoEtirtwbQlxFi9cgAwvCtul/QZBqDUFwKqx9DSm8aHKgJ1r2OMvNtsFAa4dzU6ODJzRzD+pqNw58LLKLnVxRYdhDxjdPbRHyRSpkSGvg9VGQXUuWGU+uOcxTDhqGGn9zc0LncDtA940X9RAQNcnD2YF1xWYKtVyglmITbD/I/bIeoAQYHRDZ3lLTIRJZscKUw7z1SI65/zZXPtOnGBw==\",\"signType\":\"RSA\"}"), CertFileUtil.getPrivateKeyFromPfxFile("CFCA_FM.pfx", "Eo6sZ7")));
    }
    /**
     * 解密AES密钥，然后用AES密钥对返回结果进行解密
     *
     * @param json 根据返回结果得到的json对象
     * @param privateKey 商户私钥
     * @return 解密后的http response
     */
    public static String decryptResult(JSONObject json, String privateKey) throws Exception {
        String encryptedRandomKey = json.getString("randomKeyEncrypt");
        String encryptType = json.getString("encryptType");
        Encryptor encryptor = VerifyAndDecryptUtil.getEncryptor(encryptType);
        String randomKey = encryptor.decrypt(encryptedRandomKey, privateKey);
        return AESUtils.decrypt(json.getString("data"), randomKey);
    }
}
